package app.v1.wdt.service.impl;

import app.common.utils.QmUtils;
import app.common.utils.Retry;
import app.common.utils.YdApi;
import app.common.utils.cjt.CJtUtils;
import app.common.utils.cjt.ao.SaleDeliveryCreateAo;
import app.common.utils.cjt.ao.WmsStockoutSalesQueryWithDetailAo;
import app.v1.wdt.domain.event.SalesOrderDetailsGroupByShopStatisticsEvent;
import app.v1.wdt.domain.event.SalesOrderDetailsGroupByShopWarehouseStatisticsEvent;
import app.v1.wdt.domain.pojo.WdtSalesOrder;
import app.v1.wdt.domain.pojo.WdtSalesOrderDetails;
import app.v1.wdt.domain.vo.GroupByShopNoAndSpecNoVo;
import app.v1.wdt.mapper.WdtSalesOrderDetailsMapper;
import app.v1.wdt.service.WdtSalesOrderDetailsService;
import app.v1.wdt.service.WdtSalesOrderIdGeneratorService;
import app.v1.wdt.service.WdtSalesOrderService;
import com.alibaba.fastjson.JSON;
import com.qimencloud.api.scene3ldsmu02o9.response.WdtWmsStockoutSalesQuerywithdetailResponse;
import com.taobao.api.ApiException;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author feizns
 * @since 2023/7/19
 */
@Service
@RequiredArgsConstructor
public class WdtSalesOrderDetailsServiceImpl implements WdtSalesOrderDetailsService {

    /**
     * 映射器
     */
    private final WdtSalesOrderDetailsMapper mapper;

    /**
     * 编号发电机服务
     */
    private final WdtSalesOrderIdGeneratorService idGeneratorService;

    /**
     * 事件发布者
     */
    private final ApplicationEventPublisher eventPublisher;

    @Override
    public void pullSalesOrderDetailsFromQmWdt(LocalDateTime startTime, LocalDateTime endTime) {
        while ( startTime.isBefore(endTime) ) {
            WmsStockoutSalesQueryWithDetailAo ao = new WmsStockoutSalesQueryWithDetailAo(startTime);
            //奇门店铺
            try {
                QmUtils.wdtWmsStockoutSalesQuerywithdetail(ao, order -> saveSalesOrderDetails(order, SaleDeliveryCreateAo.Dto.from(order)));
            } catch (ApiException e) {
                e.printStackTrace();
            }
            startTime = startTime.plusHours(1);
        }
    }

    @Override
    public void statisticsSalesOrderDetails(LocalDate startDate, LocalDate endDate) {
        while ( startDate.isBefore(endDate) ) {
            statisticsSalesOrderDetails(startDate);
            startDate = startDate.plusDays(1);
        }
    }

    @Override
    public void deleteSalesOrderDetails(LocalDate date) {
        mapper.deleteByConsignDate(date);
    }

    @Override
    public void statisticsSalesOrderDetails(LocalDate date) {
        //查询对应日期的数据
        List<GroupByShopNoAndSpecNoVo> vos = mapper.groupingByShopNoAndSpecNoAndConsignDate(null, date);
        //统计
        statisticsSalesOrderDetails(vos);
    }

    @Override
    public void statisticsSalesOrderDetails(LocalDate date, String shopNo, String warehouseNo) {
        //查询对应日期的数据
        List<GroupByShopNoAndSpecNoVo> vos = mapper.groupingByConsignDateByShopNoAndWarehouseNo(date, shopNo, warehouseNo);
        //统计
        statisticsSalesOrderDetails(vos);
    }

    @Override
    public void statisticsSalesOrderDetails(List<GroupByShopNoAndSpecNoVo> vos) {
        //根据店铺编号分组
        Map<String, List<GroupByShopNoAndSpecNoVo>> shopNoMap = vos.stream().collect(Collectors.groupingBy(GroupByShopNoAndSpecNoVo::getShopNo));
        //派发对应店铺的统计事件
        shopNoMap.forEach((k, v) -> eventPublisher.publishEvent(new SalesOrderDetailsGroupByShopStatisticsEvent(k, v)));
    }


    @Override
    public long countingByOrderNo(String orderNo) {
        return mapper.countingByOrderNo(orderNo);
    }

    @Override
    public void handleSalesOrderDetailsSendToYiDaShopAndSpecNoGroupStatistics(SalesOrderDetailsGroupByShopStatisticsEvent event) {
        //店铺组和商品信息响应参数
        List<GroupByShopNoAndSpecNoVo> vos = event.vos();
        //按商品分组
        Map<String, List<GroupByShopNoAndSpecNoVo>> specNoMap = vos.stream().collect(Collectors.groupingBy(GroupByShopNoAndSpecNoVo::getSpecNo));
        //处理对应商品的分组
        specNoMap.forEach((k, v) -> {
            //获取商品分组量
            GroupByShopNoAndSpecNoVo vo = v.get(0);
            //礼物数
            int giftCount = v.stream().mapToInt(GroupByShopNoAndSpecNoVo::getGiftCount).sum();
            //商品数量
            long goodsCount = v.stream().mapToLong(GroupByShopNoAndSpecNoVo::getGoodsCount).sum();
            //总价
            BigDecimal shareAmount = v.stream().map(GroupByShopNoAndSpecNoVo::getShareAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            //构建表单数据
            HashMap<String, Object> data = new HashMap<>() {{
                put("textField_laxmswy0", vo.getConsignDate());
                put("textField_kwzkmug", vo.getShopName());
                put("textField_ox80nx5", vo.getGroupId());
                put("textField_lhpqow4y", vo.getWarehouseName());
                put("textField_y5svwrw", vo.getSpecNo());
                put("textField_1rn5ro7", vo.getBrandName());
                put("textField_1myfp16", vo.getGoodsNo());
                put("textField_jjm1qxe", vo.getGoodsName());
                put("textField_jg08sea", vo.getSpecCode());
                put("textField_h5hnrp7", vo.getSpecName());
                put("numberField_3u62bv2", giftCount);
                put("numberField_dz9luu2", goodsCount);
                put("numberField_gsnrt8y", goodsCount);
                put("numberField_d8vdvot", shareAmount);
                put("textField_lhvemnz0", "Open Api.");
            }};
            //将数据统计到宜搭表单、最大重试三次
            Retry.setting(3).execute(() -> YdApi.yiDaUtils.forms.insert("FORM-33666CB1LI646OZXEQL078UISU4D2PEP0RD9LX2", data));
            String tmp = String.format("日期：%s 插入表单：单品销售日统计 店铺编号：%s 商品编号：%s 数据：%s", vo.getConsignDate(), vo.getShopNo(), vo.getSpecNo(), data);
            System.out.println(tmp);
        });
    }

    @Override
    public void dispatcherSalesOrderDetailsShopAndWarehouseGroupStatisticsEvent(SalesOrderDetailsGroupByShopStatisticsEvent event) {
        //商铺编号
        String shopNo = event.shopNo();
        //响应
        List<GroupByShopNoAndSpecNoVo> vos = event.vos();
        //仓库编号映射
        Map<String, List<GroupByShopNoAndSpecNoVo>> warehouseNoMap = vos.stream().collect(Collectors.groupingBy(GroupByShopNoAndSpecNoVo::getWarehouseNo));
        //派发对应仓库的事件
        warehouseNoMap.forEach((k, v) -> eventPublisher.publishEvent(new SalesOrderDetailsGroupByShopWarehouseStatisticsEvent(shopNo, k, v)));
    }

    @Override
    public void handleSalesOrderDetailsSendToYiDaShopAndWarehouseGroupStatistics(SalesOrderDetailsGroupByShopWarehouseStatisticsEvent event) {
        //响应列表
        List<GroupByShopNoAndSpecNoVo> vos = event.vos();
        //更新数据到宜搭（一条货品一条数据）
        for (GroupByShopNoAndSpecNoVo vo : vos) {
            //添加到宜搭
            Map<String, Object> data = new HashMap<>(){{
                    put("textField_laxmswy0", vo.getConsignDate());
                    put("textField_kwzkmug", vo.getShopName());
                    put("textField_ox80nx5", vo.getGroupId());
                    put("textField_lhpqow4y", vo.getWarehouseName());
                    put("textField_y5svwrw", vo.getSpecNo());
                    put("textField_1rn5ro7", vo.getBrandName());
                    put("textField_1myfp16", vo.getGoodsNo());
                    put("textField_jjm1qxe", vo.getGoodsName());
                    put("textField_jg08sea", vo.getSpecCode());
                    put("textField_h5hnrp7", vo.getSpecName());
                    put("numberField_dz9luu2", vo.getGoodsCount());
                    put("numberField_gsnrt8y", vo.getGoodsCount());
                    put("numberField_d8vdvot", vo.getShareAmount());
                    put("numberField_3u62bv2", vo.getGiftCount());
                    put("textField_lhvemnz0", "Open Api.");
            }};
            Retry.setting(3).execute(() -> YdApi.yiDaUtils.forms.insert("FORM-Y6666RA12JPAW7LMFYYT543K2P8Y2J9OOQPHLG", data));
            String tmp = String.format("日期：%s 插入表单：单品销售日统计（分仓库） 店铺编号：%s 仓库编号：%s 商品编号：%s 数据：%s", vo.getConsignDate(), vo.getShopNo(), vo.getWarehouseNo(), vo.getSpecNo(), data);
            System.out.println(tmp);
        }
    }

    @Override
    public void handleSalesOrderDetailsSendToCjtShopAndWarehouseGroupStatistics(SalesOrderDetailsGroupByShopWarehouseStatisticsEvent event) {
        //店铺编号
        String shopNo = event.shopNo();
        //仓库编号
        String warehouseNo = event.warehouseNo();
        //列表值
        List<GroupByShopNoAndSpecNoVo> vos = event.vos();
        //按发货日期分组
        Map<LocalDate, List<GroupByShopNoAndSpecNoVo>> groupByConsignDate = vos.stream().collect(Collectors.groupingBy(GroupByShopNoAndSpecNoVo::getConsignDate));
        //将数据接入
        groupByConsignDate.forEach((consignDate, v) -> {
            //销售单
            SaleDeliveryCreateAo.Dto dto = new SaleDeliveryCreateAo.Dto();
            dto.setBusinessType(new SaleDeliveryCreateAo.Dto.BusinessType("15"));
            String orderNo = idGeneratorService.nextOrderNo(shopNo, warehouseNo, consignDate);
            dto.setExternalCode(orderNo);
            dto.setProject(new SaleDeliveryCreateAo.Dto.Project(shopNo));
            dto.setCustomer(new SaleDeliveryCreateAo.Dto.Customer(shopNo));
            dto.setCode(orderNo);
            dto.setWarehouse(new SaleDeliveryCreateAo.Dto.Warehouse(warehouseNo));
            dto.setVoucherDate(consignDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            dto.setMemo(String.format("来源：[旺店通] 表单：[销售出库单] 编号：[%s] 仓库:[%s] 备注：[%s]", dto.getExternalCode(), warehouseNo, "日销售统计"));
//            dto.setMemo(String.format("[测试]:编号：[%s] 类型：[%s] 仓库:[%s] 备注：[%s]", dto.getExternalCode(), "销售出库单", warehouseNo, "日统计生成"));
            //整理对应仓库下的所有商品
            List<SaleDeliveryCreateAo.Dto.SaleDeliveryDetails> objects = v.stream().map(vo -> {
                SaleDeliveryCreateAo.Dto.SaleDeliveryDetails detail = new SaleDeliveryCreateAo.Dto.SaleDeliveryDetails();
                detail.setInventory(new SaleDeliveryCreateAo.Dto.SaleDeliveryDetails.Inventory(vo.getSpecNo()));
                detail.setQuantity(vo.getGoodsCount());
                detail.setOrigDiscountPrice(vo.getMarketPrice());
                detail.setTaxRate(vo.getTaxRate());
                detail.setOrigDiscountAmount(vo.getShareAmount());
                detail.setOrigTaxPrice(detail.getOrigDiscountPrice());
                detail.setOrigTaxAmount(detail.getOrigDiscountAmount());
                detail.setUnit(new SaleDeliveryCreateAo.Dto.SaleDeliveryDetails.Unit(vo.getUnitName()));
                return detail;
            }).collect(Collectors.toList());
            dto.setSaleDeliveryDetails(objects);
            //添加数据
            WdtSalesOrder order = WdtSalesOrderService.getByOrderNo(dto.getExternalCode());
            if ( order == null )
                order = new WdtSalesOrder();
            if ( !order.isSuccessfully() ) {
                order.setOrderNo(dto.getExternalCode());
                order.setDto(JSON.toJSONString(dto));
                String message;
                try {
                    message = CJtUtils.saleDeliveryCreate(dto);
                } catch (Exception e) {
                    message = e.getMessage();
                }
                order.setMessage(message);
                order.insertOrUpdate();
            }
        });
    }

    @Transactional
    public void saveSalesOrderDetails(WdtWmsStockoutSalesQuerywithdetailResponse.Order order, SaleDeliveryCreateAo.Dto dto) {
        if ( !existsByOrderNo(order.getOrderNo()) )
            WdtSalesOrderDetails.toWdtSalesOrderDetailsList(order, dto)
                    .forEach(WdtSalesOrderDetails::insert);
    }

}
